package com.pangolin.pangolinim.utils;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;

import androidx.documentfile.provider.DocumentFile;

import com.orhanobut.logger.Logger;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.util.Random;

public class FileUtil {
    /**
     TODO：将文件数据写入用户私有目录
     @param context 上下文context
     @param filename 存放于getExternalFilesDir的uid目录下的文件名
     @param dirname 二级目录名称
     @param data byte[]文件数据
     */
    public static void writeToPrivate(Context context , String filename , String dirname , byte [] data) throws IOException {
        //检查目录是否存在
        File userDir = context.getExternalFilesDir(String.valueOf(dirname));
        if(!userDir.exists()){
            userDir.mkdirs();
        }
        //创建并写入文件
        File file= new File(userDir , filename);
        if (!file.exists()) {
            file.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(data);
        fos.flush();
        fos.close();
    }

    /**
     TODO：AndroidQ及以上，将DCIM目录下文件拷贝到用户私有目录的根目录下，文件名随机命名。
     @param context 上下文context
     @param dcimUri 存放于DCIM目录下的文件uri
     @param dstHeight 目标图像的高度
     @param dstWidth 目标图像宽度
     @return 返回临时文件名
     */
    private static String _copyGalleryToPrivateQ(
            Context context ,
            Uri dcimUri ,
            int dstHeight ,
            int dstWidth) throws IOException{
        Bitmap bm = MediaStore.Images.Media.getBitmap(context.getContentResolver(), dcimUri);
        String TmpFile = GetTmpFileName();
        //创建并写入文件
        File file= new File(context.getExternalFilesDir(null) , TmpFile);
        if (!file.exists()) {
            file.createNewFile();
        }
        FileOutputStream out = new FileOutputStream(file);
        // 获得图片的宽高
        int width = bm.getWidth();
        int height = bm.getHeight();
        // 计算缩放比例
        float scaleWidth = ((float) dstWidth) / width;
        float scaleHeight = ((float) dstHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix,true);
        newbm.compress(Bitmap.CompressFormat.JPEG, 100, out);
        bm.recycle();
        newbm.recycle();
        out.flush();
        out.close();
        return TmpFile;
    }

    /**
     TODO：AndroidQ以下，将DCIM目录下文件拷贝到用户私有目录的根目录下，文件名随机命名。
     @param context 上下文context
     @param dcimUri 存放于DCIM目录下的uri
     @param dstHeight 目标图像的高度
     @param dstWidth 目标图像宽度
     @return 返回临时文件名
     */
    private static String _copyGalleryToPrivate(
            Context context ,
            Uri dcimUri ,
            int dstHeight ,
            int dstWidth) throws IOException{
        Bitmap bm= BitmapFactory.decodeFile(dcimUri.getPath());
        String TmpFile = GetTmpFileName();
        //创建并写入文件
        File dstFile= new File(context.getExternalFilesDir(null) , TmpFile);
        FileOutputStream out = new FileOutputStream(dstFile);
        // 获得图片的宽高
        int width = bm.getWidth();
        int height = bm.getHeight();
        // 计算缩放比例
        float scaleWidth = ((float) dstWidth) / width;
        float scaleHeight = ((float) dstHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix,true);
        newbm.compress(Bitmap.CompressFormat.JPEG, 100, out);
        bm.recycle();
        newbm.recycle();
        out.flush();
        out.close();
        return TmpFile;
    }

    /**
     TODO：AndroidQ及以上，将用户私有目录（uid命名的文件夹下）的文件拷贝到DCIM目录下
     @param context 上下文context
     @param srcfile 存放于私有目录下的文件名
     */
    private static void _copyPrivateToGalleryQ(Context context , File srcfile) throws IOException{
        ContentValues values = new ContentValues();
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, srcfile.getName());
        values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
        values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM+"/Pangolin/");

        ContentResolver resolver = context.getContentResolver();

        Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

        OutputStream fos = context.getContentResolver().openOutputStream(uri);
        FileInputStream fis = new FileInputStream(srcfile);
        if(fos != null && fis != null){
            byte[] buffer = new byte[1024];
            int byteCount = 0;
            while ((byteCount = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, byteCount);
            }
        }
        fos.close();
        fis.close();
    }

    /**
     TODO：AndroidQ以下，将用户私有目录（uid命名的文件夹下）的文件拷贝到DCIM目录下
     @param context 上下文context
     @param srcfile 存放于私有目录下的文件名
     */
    private static void _copyPrivateToGallery(Context context , File srcfile) throws IOException{
        File imgDir = new File(Environment.getExternalStorageDirectory()+"/DCIM/" , "Pangolin");
        if(!imgDir.exists()){
            imgDir.mkdir();
        }
        //拷贝文件到sdcark/pangolin目录下
        File dstFile= new File(imgDir , srcfile.getName());
        FileChannel inputStream = new FileInputStream(srcfile).getChannel();
        FileChannel outputStream = new FileOutputStream(dstFile).getChannel();

        if (outputStream!=null && inputStream != null){
            outputStream.transferFrom(inputStream,0,inputStream.size());
        }
        inputStream.close();
        outputStream.close();
        // 其次把文件插入到系统图库
        MediaStore.Images.Media.insertImage(context.getContentResolver(), dstFile.getPath(), srcfile.getName(), null);
        // 通知系统相册
        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + dstFile.getPath())));
    }

    /**
     TODO：将用户私有目录的文件拷贝到DCIM目录下
     @param context 上下文context
     @param srcfile 存放于私有目录下的文件名
     */
    public static void copyPrivateToGallery(Context context, File srcfile) throws Exception{
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            _copyPrivateToGalleryQ(context , srcfile);
        }else{
            _copyPrivateToGallery(context , srcfile);
        }
    }

    /**
     TODO：将DCIM目录下文件拷贝到用户私有目录
     @param context 上下文context
     @param dcimUri 存放于DCIM目录下的uri
     @param dstDirname 目标文件夹名称
     @param dstHeight 目标图像的高度
     @param dstWidth 目标图像宽度
     @return 拷贝到私有目录的文件名
     */
    public static String copyGalleryToPrivate(
            Context context ,
            Uri dcimUri ,
            String dstDirname ,
            int dstHeight ,
            int dstWidth) throws Exception{
        //检查目录是否存在
        File userDir = context.getExternalFilesDir(dstDirname);
        if(!userDir.exists()){
            userDir.mkdirs();
        }
        String TmpFile;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            TmpFile = _copyGalleryToPrivateQ(context , dcimUri , dstHeight , dstWidth);
        }else{
            TmpFile = _copyGalleryToPrivate(context , dcimUri , dstHeight , dstWidth);
        }
        //重命名文件，返回新的文件名
        File file= new File(context.getExternalFilesDir(null) , TmpFile);
        String md5Filename = getFileMD5(file);
        md5Filename = md5Filename + ".jpg";
        File newfile = new File(context.getExternalFilesDir(dstDirname) , md5Filename);
        file.renameTo(newfile);
        return md5Filename;
    }

    /**
     TODO：获取文件md5值
     @param file 文件句柄
     */
    private static String getFileMD5(File file) throws Exception{
        if (!file.isFile()) {
            return null;
        }
        MessageDigest digest = null;
        FileInputStream in = null;
        byte buffer[] = new byte[1024];
        int len;
        digest = MessageDigest.getInstance("MD5");
        in = new FileInputStream(file);
        while ((len = in.read(buffer, 0, 1024)) != -1) {
            digest.update(buffer, 0, len);
        }
        in.close();
        BigInteger bigInt = new BigInteger(1, digest.digest());
        return bigInt.toString(16);
    }

    /**
     * TODO:获取随机文件名，格式为Tmp_[6位随机英文字符]_时间戳
     * @return 随机文件名
     */
    private static String GetTmpFileName(){
        String TmpFile = "Tmp_" + getRandomString(6) + Long.toString(System.currentTimeMillis());
        return TmpFile;
    }

    /**
     * TODO:生成包含英文小写的随机字符串
     * @param length 字符串长度
     * @return 随机字符串
     */
    private static String getRandomString(int length){
        String str="abcdefghijklmnopqrstuvwxyz";
        Random random=new Random();
        StringBuffer sb=new StringBuffer();
        for(int i=0;i<length;i++){
            int number=random.nextInt(26);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }

//    /**
//     * TODO：从URI中获取文件真实文件名
//     * @param context 上下文context
//     * @param uri   文件uri
//     * @return  返回真实文件名
//     */
//    private static String getFileRealNameFromUri(Context context, Uri uri) {
//        Logger.d("getFileRealNameFromUri:%s" , uri.getPath());
//        if (context == null || uri == null) return null;
//        DocumentFile documentFile = DocumentFile.fromSingleUri(context, uri);
//        if (documentFile == null) return null;
//        return documentFile.getName();
//    }
}
